import * as THREE from 'three';
import { GLTFLoader } from 'three/examples/jsm/loaders/GLTFLoader';
import { DRACOLoader } from 'three/examples/jsm/loaders/DRACOLoader';
import { FBXLoader } from 'three/examples/jsm/loaders/FBXLoader';
import { FontLoader } from 'three/examples/jsm/loaders/FontLoader.js';
import { TextGeometry } from 'three/examples/jsm/geometries/TextGeometry.js';
let font: any,
  fontName: string = 'droid_sans', // 字体名称
  fontWeight: string = 'regular', // 字体粗细
  loader = new GLTFLoader(),
  dracoLoader = new DRACOLoader();

// 画布自适应
export const onWindowResize = (
  camera: THREE.Camera,
  renderer: THREE.WebGLRenderer
) => {
  if (renderer) {
    camera.aspect = window.innerWidth / window.innerHeight;
    camera.updateProjectionMatrix();
    renderer.setPixelRatio(window.devicePixelRatio);
    renderer.setSize(window.innerWidth, window.innerHeight);
  }
};

export const addMeshLight = (mesh: any, bri: number) => {
  const basicColor = mesh.color;
  const newColor = new THREE.Color(
    basicColor.r * bri,
    basicColor.g * bri,
    basicColor.b * bri
  );
  mesh.color.set(newColor);
};

// 获取图片Texture
export const getTexture = async (path: string, params?: any) => {
  const textureLoader = new THREE.TextureLoader();
  let texture = await textureLoader.loadAsync(path);
  if (params?.colorSpace) {
    texture.colorSpace = THREE.SRGBColorSpace; // 设置颜色空间为 sRGB
  }
  texture.wrapS = texture.wrapT = THREE.RepeatWrapping;
  texture.repeat.set(params?.repeat?.x || 1, params?.repeat?.y || 1);
  texture.needsUpdate = true; // 确保纹理更新
  return texture;
};

export const getModel = async (name: string, fun: Function) => {
  dracoLoader.setDecoderPath('draco/');
  loader = !loader ? new GLTFLoader() : loader;
  if (name.indexOf('.fbx') != -1) loader = new FBXLoader();
  loader.setDRACOLoader(dracoLoader);
  await loader.load(`static/${name}`, (model: any) => {
    fun(model);
  });
};

// 获取字体
export const getTextGeometry = async (str: string) => {
  str += '';
  if (!font) {
    const loader = new FontLoader();
    const path = `/fonts/${fontName}_${fontWeight}.typeface.json`;
    font = await loader.loadAsync(path);
    return new TextGeometry(str, { font, size: 0.3 });
  } else {
    return new TextGeometry(str, { font, size: 0.3 });
  }
};

// 清除组
export const clearGroup = (group: any) => {
  const clearCache = (item: any) => {
    item.geometry && item.geometry.dispose();
    if (item.material) {
      if (item.material.length > 0) {
        item.material.map((v: any) => v.dispose());
      } else {
        item.material.dispose();
      }
    }
  };

  const removeObj = (obj: any) => {
    let arr = obj.children.filter((x: any) => x);
    arr.forEach((item: any) => {
      if (item.children.length) {
        removeObj(item);
      } else {
        clearCache(item);
        item.clear();
      }
    });
    obj.clear();
    arr = null;
  };

  removeObj(group);
};

// 更新文字
export const upDateTextPos = async (obj: any) => {
  const geometry = await getTextGeometry(obj.startTroops + '');
  obj.children[0].children[0].geometry = geometry;
  let fontMesh = obj.children[0].children[0];
  let bgMesh = fontMesh.parent;
  const size = getPos(fontMesh, 'size');
  fontMesh.position.set(bgMesh.centerPos.x, bgMesh.centerPos.y, 0.1);
  fontMesh.translateX(-(size.x / 1.7));
  fontMesh.translateY(-(size.y / 2.2));
};

// 获取对象大小/中心点
export const getPos = (Mesh: any, type?: any) => {
  const box = new THREE.Box3().setFromObject(Mesh);
  const center = new THREE.Vector3();
  const size = new THREE.Vector3();
  box.getCenter(center);
  box.getSize(size);
  return type == 'size' ? size : center;
};

export const cameraFarAuto = (camera: any, Mesh: any) => {
  let aspect = window.innerWidth / window.innerHeight;
  let scale = 0.5;
  const size = getPos(Mesh, 'size');
  const cameraDistance = (size.length() * scale) / aspect; // 将相机放置在距离模型2倍尺寸的地方
  const center = getPos(Mesh);
  let ePos = new THREE.Vector3(center.x, center.y, cameraDistance);
  return ePos;
};

// 获取鼠标/触摸事件屏幕坐标点
export const getOnPos = (event: any) => {
  let Pos = { x: 0, y: 0 };
  let posX = event?.clientX;
  let posY = event?.clientY;
  if (event.targetTouches) {
    posX = event.targetTouches[0].clientX;
    posY = event.targetTouches[0].clientY;
  }
  Pos.x = (posX / window.innerWidth) * 2 - 1;
  Pos.y = -(posY / window.innerHeight) * 2 + 1;
  return Pos;
};

export const sleep = (num: any) => {
  return new Promise((resolve) => {
    setTimeout(() => {
      resolve('');
    }, num);
  });
};
